home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 21 / Cream of the Crop 21 (Terry Blount) (October 1996).iso / os2 / e33el2.zip / emacs / 19.33 / lisp / refer.el < prev    next >
Lisp/Scheme  |  1996-01-20  |  10KB  |  231 lines

  1. ;;; refer.el --- look up references in bibliography files.
  2.  
  3. ;; Copyright (C) 1992 Free Software Foundation, Inc.
  4.  
  5. ;; Author: Ashwin Ram <Ram-Ashwin@cs.yale.edu>
  6. ;; Adapted-By: ESR
  7. ;; Keywords: bib
  8.  
  9. ;; This file is part of GNU Emacs.
  10.  
  11. ;; GNU Emacs is free software; you can redistribute it and/or modify
  12. ;; it under the terms of the GNU General Public License as published by
  13. ;; the Free Software Foundation; either version 2, or (at your option)
  14. ;; any later version.
  15.  
  16. ;; GNU Emacs is distributed in the hope that it will be useful,
  17. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  18. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  19. ;; GNU General Public License for more details.
  20.  
  21. ;; You should have received a copy of the GNU General Public License
  22. ;; along with GNU Emacs; see the file COPYING.  If not, write to the
  23. ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  24. ;; Boston, MA 02111-1307, USA.
  25.  
  26. ;;; Commentary:
  27.  
  28. ;; Functions to look up references in bibliography files given lists of
  29. ;; keywords, similar to refer(1).  I don't use tags since tags on .bib files
  30. ;; only picks up the cite key, where as refer-find-entry looks for occurrences
  31. ;; of keywords anywhere in the bibliography entry.
  32. ;;
  33. ;; To use:
  34. ;;      (autoload 'refer-find-entry "refer" nil t)
  35. ;; or   (require 'refer)
  36. ;;
  37. ;;      To look for an article by Knuth about semaphores:
  38. ;;          Invoke refer-find-entry, then in response to the Keywords: prompt,
  39. ;;          say: Knuth semaphores (a blank-separated list of keywords to be used
  40. ;;          as search strings).
  41. ;;
  42. ;;      To continue the previous search, i.e., to search for the next occurrence
  43. ;;      of the keywords, use refer-find-next-entry, or invoke refer-find-entry
  44. ;;      with a prefix argument.
  45. ;;
  46. ;;      If the list of bibliography files changes, reinitialize the variable
  47. ;;      refer-bib-files.
  48. ;;
  49. ;; To customize:
  50. ;;      See variables refer-bib-files, refer-cache-bib-files and
  51. ;;      refer-bib-files-regexp.  By default, these are set up so that refer
  52. ;;      looks for the keywords you specify in all the .bib files in the current
  53. ;;      directory.
  54. ;;
  55. ;;      The only assumption I make about bib files is that they contain a bunch
  56. ;;      of entries, one to a paragraph.  refer-find-entry searches paragraph by
  57. ;;      paragraph, looking for a paragraph containing all the keywords
  58. ;;      specified.  So you should be able to use pretty much any bib file with
  59. ;;      this code.  If your bib file does not use paragraphs to separate
  60. ;;      entries, try setting the paragraph-start/separate variables, or changing
  61. ;;      the (forward-paragraph 1) call in refer-find-entry-in-file.
  62.  
  63. ;;; ChangeLog:
  64.  
  65. ;; 01/08/89 Ashwin Ram <Ram-Ashwin@cs.yale.edu>
  66. ;;          Initial release.
  67. ;;
  68.  
  69. ;;; Code:
  70.  
  71. (provide 'refer)
  72.  
  73. (defvar refer-bib-files 'dir
  74.    "*List of \\.bib files to search for references,
  75. or one of the following special values:
  76. nil  = prompt for \\.bib file (if visiting a \\.bib file, use it as default)
  77. auto = read \\.bib file names from appropriate command in buffer (see refer-bib-files-regexp)
  78. dir  = use all \\.bib files in current directory.
  79.  
  80. If a specified file doesn't exist and has no extension, a \\.bib extension
  81. is automatically tried.
  82.  
  83. If refer-bib-files is nil, auto or dir, it is setq'd to the appropriate
  84. list of files when it is first used if refer-cache-bib-files is t.  If
  85. refer-cache-bib-files is nil, the list of \\.bib files to use is re-read
  86. each time it is needed.")
  87.  
  88. (defvar refer-cache-bib-files t
  89.    "*Variable determining whether the value of refer-bib-files should be cached.
  90. If t, initialize the value of refer-bib-files the first time it is used.  If
  91. nil, re-read the list of \\.bib files depending on the value of refer-bib-files
  92. each time it is needed.")
  93.  
  94. (defvar refer-bib-files-regexp "\\\\bibliography"
  95.    "*Regexp matching a bibliography file declaration.
  96. The current buffer is expected to contain a line such as
  97. \\bibliography{file1,file2,file3}
  98. which is read to set up refer-bib-files.  The regexp must specify the command
  99. \(such as \\bibliography) that is used to specify the list of bib files.  The
  100. command is expected to specify a file name, or a list of comma-separated file
  101. names, within curly braces.
  102. If a specified file doesn't exist and has no extension, a \\.bib extension
  103. is automatically tried.")
  104.  
  105. (make-variable-buffer-local 'refer-bib-files)
  106. (make-variable-buffer-local 'refer-cache-bib-files)
  107.  
  108. (defun refer-find-entry (keywords &optional continue)
  109.    "Find entry in refer-bib-files containing KEYWORDS.
  110. If KEYWORDS is nil, prompt user for blank-separated list of keywords.
  111. If CONTINUE is t, or if called interactively with a prefix arg, look for next
  112. entry by continuing search from previous point."
  113.    (interactive (list nil current-prefix-arg))
  114.    (or keywords (setq keywords (if continue
  115.                                    refer-previous-keywords
  116.                                    (read-string "Keywords: "))))
  117.    (setq refer-previous-keywords keywords)
  118.    (refer-find-entry-internal keywords continue))
  119.  
  120. (defun refer-find-next-entry ()
  121.    "Find next occurrence of entry in refer-bib-files.  See refer-find-entry."
  122.    (interactive)
  123.    (refer-find-entry-internal refer-previous-keywords t))
  124.  
  125. (defun refer-find-entry-internal (keywords continue)
  126.    (let ((keywords-list (refer-convert-string-to-list-of-strings keywords))
  127.          (files (if continue
  128.                     refer-saved-state
  129.                     (refer-get-bib-files))))
  130.       (catch 'found
  131.          (while files
  132.             (let ((file (cond ((file-exists-p (car files)) (car files))
  133.                               ((file-exists-p (concat (car files) ".bib")) (concat (car files) ".bib")))))
  134.                (setq refer-saved-state files)
  135.                (if file
  136.                    (if (refer-find-entry-in-file keywords-list file continue)
  137.                        (throw 'found (find-file file))
  138.                        (setq files (cdr files)))
  139.                    (progn (message "Scanning %s... No such file" (car files) (ding))
  140.                           (sit-for 1)
  141.                           (setq files (cdr files))))))
  142.          (message "Keywords \"%s\" not found in any \.bib file" keywords (ding)))))
  143.  
  144. (defun refer-find-entry-in-file (keywords-list file &optional continue)
  145.    (message "Scanning %s..." file) ; (expand-file-name file)
  146.    (set-buffer (find-file-noselect file))
  147.    (if continue
  148.        (forward-paragraph 1)
  149.        (goto-char (point-min)))
  150.    (let ((begin (point))
  151.          (end 0)
  152.          (found nil))
  153.       (while (and (not found)
  154.                   (not (eobp)))
  155.          (forward-paragraph 1)
  156.          (setq end (point))
  157.          (setq found
  158.                (refer-every (function (lambda (keyword)
  159.                     (goto-char begin)
  160.                     (re-search-forward keyword end t)))
  161.                 keywords-list))
  162.          (if (not found)
  163.              (progn
  164.                 (setq begin end)
  165.                 (goto-char begin))))
  166.       (if found
  167.           (progn (goto-char begin)
  168.                  (re-search-forward "\\W" nil t)
  169.                  (message "Scanning %s... found" file))
  170.           (progn (message "Scanning %s... not found" file)
  171.                  nil))))
  172.  
  173. (defun refer-every (pred l)
  174.    (cond ((null l) nil)
  175.          ((funcall pred (car l))
  176.           (or (null (cdr l))
  177.               (refer-every pred (cdr l))))))
  178.  
  179. (defun refer-convert-string-to-list-of-strings (s)
  180.    (let ((current (current-buffer))
  181.          (temp-buffer (get-buffer-create "*refer-temp*")))
  182.       (set-buffer temp-buffer)
  183.       (erase-buffer)
  184.       (insert (regexp-quote s))
  185.       (goto-char (point-min))
  186.       (insert "(\"")
  187.       (while (re-search-forward "[ \t]+" nil t)
  188.          (replace-match "\" \"" t t))
  189.       (goto-char (point-max))
  190.       (insert "\")")
  191.       (goto-char (point-min))
  192.       (prog1 (read temp-buffer)
  193.          (set-buffer current))))
  194.  
  195. (defun refer-get-bib-files ()
  196.    (let ((files
  197.            (cond ((null refer-bib-files) 
  198.                   (list (expand-file-name
  199.